package com.hliushi.redis.controller;

import com.hliushi.redis.controller.vo.Product;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * @author llhuang10
 * @date 2021/8/4 21:12
 */
@Slf4j
@RestController
@RequestMapping("/api")
public class ProductController {


    /**
     * Hash --> Map<String, HashMap<String, String>> hash = new HashMap<>()
     */
    @Resource
    private RedisTemplate redisTemplate;


    /**
     * @param
     * @return
     */
    @PostMapping("/create")
    public ResponseEntity<String> create(Product vo) {
        // TODO 先进db

        // 创建商品, 先把数据添加到数据库, 再存入redis
        String key = "product:" + vo.getId();
        // 将Object对象里面的属性和值转化为map对象
        Map<String, Object> map = this.objectToMap(vo);
        // 批量put操作 putAll 等于 hmset命令
        redisTemplate.opsForHash().putAll(key, map);
        //
        Object name = redisTemplate.opsForHash().get(key, Product.Fields.name);
        log.info("name = {}", name);
        Object price = redisTemplate.opsForHash().get(key, Product.Fields.price);
        log.info("price = {}", price);
        Object detail = redisTemplate.opsForHash().get(key, Product.Fields.detail);
        log.info("detail = {}", detail);

        return ResponseEntity.ok("200");
    }

    /**
     * @param
     * @return
     */
    @PutMapping("/addPrice")
    public void addPrice(int id, int price) {
        String key = "product:" + id;

        redisTemplate.opsForHash().increment(key, Product.Fields.price, price);
        Object newPrice = redisTemplate.opsForHash().get(key, Product.Fields.price);
        log.info("newPrice = {}", newPrice);
    }

    /**
     * 将obj对象转换为 map
     *
     * @param obj
     * @return map
     */
    private Map<String, Object> objToMap(Object obj) {
        HashMap<String, Object> map = new HashMap<>(16);
        if (obj == null) {
            return map;
        }

        Class<?> clazz = obj.getClass();
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            String fileName = field.getName();
            String upperName = "get" + fileName.substring(0, 1).toUpperCase() + fileName.substring(1);
            try {
                Method method = clazz.getMethod(upperName);
                Object value = method.invoke(obj);
                map.put(fileName, value);
            } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException ex) {
                log.error("{} 类没有get{} 方法", obj.getClass(), upperName);
            }
        }

        return map;
    }


    /**
     * 将Object对象里面的属性和值转化成Map对象
     */
    public Map<String, Object> objectToMap(Object obj) {
        Map<String, Object> map = new HashMap<>();
        Class<?> clazz = obj.getClass();
        for (Field field : clazz.getDeclaredFields()) {
            field.setAccessible(true);
            String fieldName = field.getName();
            Object value = null;
            try {
                value = field.get(obj);
            } catch (IllegalAccessException e) {
                log.error(e.getMessage());
            }
            map.put(fieldName, value);
        }
        return map;
    }
}
